package cn.fufeiii.bt.common.aspect.exception;

import cn.fufeiii.bt.common.code.CommonResultEnum;
import cn.fufeiii.bt.common.util.result.BizException;
import cn.fufeiii.bt.common.util.result.CommonResult;
import lombok.extern.slf4j.Slf4j;
import org.springframework.http.HttpStatus;
import org.springframework.http.converter.HttpMessageNotReadableException;
import org.springframework.validation.BindException;
import org.springframework.validation.FieldError;
import org.springframework.web.HttpMediaTypeNotSupportedException;
import org.springframework.web.HttpRequestMethodNotSupportedException;
import org.springframework.web.bind.MissingServletRequestParameterException;
import org.springframework.web.bind.annotation.ExceptionHandler;
import org.springframework.web.bind.annotation.ResponseStatus;
import org.springframework.web.bind.annotation.RestControllerAdvice;


/**
 * 全局异常处理 通知
 *
 * @author FuFei
 */
@Slf4j
@RestControllerAdvice
public class GlobalExceptionAdvice {

    /**
     * 请求参数缺失异常
     */
    @ExceptionHandler(MissingServletRequestParameterException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Object missingParameter(MissingServletRequestParameterException exception) {
        String parameterName = exception.getParameterName();
        String reason = String.format("%s:缺少参数[%s]", CommonResultEnum.REQUEST_ABNORMALITY.getMessage(), parameterName);
        log.warn(reason);
        return CommonResult.fail(CommonResultEnum.REQUEST_ABNORMALITY.getCode(), reason);
    }


    /**
     * 拦截不支持媒体类型
     */
    @ExceptionHandler({
            HttpMediaTypeNotSupportedException.class,
            HttpRequestMethodNotSupportedException.class,
            HttpMessageNotReadableException.class
    })
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Object httpMediaTypeNotSupport(Exception exception) {
        String reason = String.format("%s:%s", CommonResultEnum.REQUEST_ABNORMALITY.getMessage(), exception.getMessage());
        log.warn(reason);
        return CommonResult.fail(CommonResultEnum.REQUEST_ABNORMALITY.getCode(), reason);
    }


    /**
     * 请求参数校验失败
     */
    @ExceptionHandler(BindException.class)
    @ResponseStatus(HttpStatus.BAD_REQUEST)
    public Object methodArgumentNotValidException(BindException exception) {
        // 使用@Vaild
        FieldError fieldError = exception.getBindingResult().getFieldError();
        String reason = "";
        if (fieldError != null) {
            reason = String.format("%s:%s", CommonResultEnum.REQUEST_ABNORMALITY.getMessage(), fieldError.getField() + fieldError.getDefaultMessage());
        }
        log.warn("参数校验失败:{}", reason);
        return CommonResult.fail(CommonResultEnum.REQUEST_ABNORMALITY.getCode(), reason);
    }


    /**
     * 业务异常
     */
    @ExceptionHandler(BizException.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Object bizException(BizException e) {
        log.warn("业务异常", e);
        return CommonResult.fail(e.getCode(), e.getMessage());
    }


    /**
     * 其他异常
     */
    @ExceptionHandler(Throwable.class)
    @ResponseStatus(HttpStatus.INTERNAL_SERVER_ERROR)
    public Object serverException(Throwable e) {
        log.warn("内部异常", e);
        return CommonResult.fail(CommonResultEnum.SERVER_FAIL.getCode(), e.getMessage());
    }

}
